package de.rs.espresso.cubes;

import de.rs.espresso.algorithms.model.FreeSet;
import de.rs.espresso.interfaces.ICover;
import de.rs.espresso.interfaces.ICube;
/**
 * Provides the possibility to freeze the state of the given {@link ICube} in order to restore it later with the {@link #getOriginalCube()}-Method.
 * 
 * @author Jan
 *
 */
public class FreezedCube implements ICube, Cloneable {

	ICube origCube;
	ICube modifiedCube;

	public FreezedCube(ICube cube) {
		this.origCube = cube;
		this.modifiedCube = cube.clone();
	}

	private FreezedCube(ICube origCube, ICube modifiedCube) {
		this.origCube = origCube;
		this.modifiedCube = modifiedCube;
	}

	@Override
	public boolean equals(Object obj) {
		return modifiedCube.equals(obj);
	}

	@Override
	public int hashCode() {
		return modifiedCube.hashCode();
	}

	public ICube getOriginalCube() {
		return origCube;
	}

	@Override
	public FreezedCube clone() {
		return new FreezedCube(origCube, modifiedCube.clone());

	}

	@Override
	public boolean isVoid() {
		return modifiedCube.isVoid();
	}

	@Override
	public boolean isTautology() {
		return modifiedCube.isTautology();
	}

	@Override
	public ICube getSupercube(ICube otherCube) {
		return getSupercube(otherCube);
	}

	@Override
	public void raisePart(int position) {
		modifiedCube.raisePart(position);

	}

	@Override
	public void lowerPart(int position) {
		modifiedCube.lowerPart(position);

	}

	@Override
	public int getNumberOfLiterals() {
		return modifiedCube.getNumberOfLiterals();
	}

	@Override
	public byte getOutput(int position) {
		return modifiedCube.getOutput(position);
	}

	@Override
	public int getNumberOfOutputs() {
		return modifiedCube.getNumberOfOutputs();
	}

	@Override
	public int[] addToColumnCount(int[] columnCount) {
		return modifiedCube.addToColumnCount(columnCount);
	}

	@Override
	public int getCubeWeight(int[] columnCount) {
		return modifiedCube.getCubeWeight(columnCount);
	}

	@Override
	public int getDistance(ICube otherCube) {
		return modifiedCube.getDistance(otherCube);
	}

	@Override
	public boolean isPartSet(int position) {
		return modifiedCube.isPartSet(position);
	}

	@Override
	public boolean intersectAt(ICube otherCube, int position) {
		return modifiedCube.intersectAt(otherCube, position);
	}

	@Override
	public boolean isVoidAt(int position) {
		return modifiedCube.isVoidAt(position);
	}

	@Override
	public FreeSet getFreeSet() {
		return modifiedCube.getFreeSet();
	}

	@Override
	public boolean covers(ICube otherCube) {
		return modifiedCube.covers(otherCube);
	}

	@Override
	public ICube getOverexpandedCube(FreeSet fSet) {
		return modifiedCube.getOverexpandedCube(fSet);
	}

	@Override
	public ICube getCofactor(ICube cube) {
		ICube coFactorCube = modifiedCube.getCofactor(cube);
		if (coFactorCube != null)
			return new FreezedCube(origCube, coFactorCube);
		else
			return null;
	}

	@Override
	public ICube or(ICube cube) {
		ICube otherCube;
		if(cube instanceof FreezedCube)
			otherCube = ((FreezedCube)cube).modifiedCube;
		else
			otherCube = cube;
		return new FreezedCube(null, modifiedCube.or(otherCube));
	}

	@Override
	public ICube and(ICube cube) {
		ICube otherCube;
		if(cube instanceof FreezedCube)
			otherCube = ((FreezedCube)cube).modifiedCube;
		else
			otherCube = cube;
		return new FreezedCube(null, modifiedCube.and(otherCube));
	}

	@Override
	public byte getLiteral(int position) {
		return modifiedCube.getLiteral(position);
	}

	@Override
	public void setLiteral(int position, byte value) {
		modifiedCube.setLiteral(position, value);
	}

	@Override
	public int countDontCares() {
		return modifiedCube.countDontCares();
	}

	@Override
	public int[][] addToDirectNegatedCount(int[][] directNegatedCount) {
		return modifiedCube.addToDirectNegatedCount(directNegatedCount);
	}

	@Override
	public void setOutput(int position, byte value) {
		modifiedCube.setOutput(position, value);

	}
	
	@Override
	public String toString() {
		return "WRAP{ "+ origCube +" -> "+ modifiedCube +" }";
		
	}

	@Override
	public ICover getComplement() {

		return modifiedCube.getComplement();
	}

	@Override
	public boolean isAlreadyExpanded() {
		return modifiedCube.isAlreadyExpanded();
	}

	@Override
	public void setAlreadyExpanded(boolean isAlreadyExpanded) {
		modifiedCube.setAlreadyExpanded(isAlreadyExpanded);
	}

	@Override
	public String getBlifString() {
		return modifiedCube.getBlifString();
	}

}
